import {
  CreateGraphicMetas,
  GraphicMeta,
  PlotTypeEnum,
  PluginObject,
} from '../type'
import { isFunction, isObject } from '@/utils/is';
import { cloneDeep, isArray } from 'lodash';
import { ref } from 'vue';
import { IObjectEditEmits, IObjectEditProps } from '../type';
import { areaGetByMeta, getZoningPlan } from '@/api/area.api';

export enum State {
  查看,
  待创建,
  待保存,
}
/**在地图上创建对象,前端传递数据的方式 */
export const createGraphicObject = (data: any[]) => {
  const params: CreateGraphicMetas[] = [];
  data.forEach((item) => {
    if (!item || !item.geometry || !item.plotProperties) return;
    params.push({
      geometry: {
        geometry: cloneDeep(item.geometry),
        properties: JSON.stringify(item.plotProperties),
        type: 'Feature',
        id: item.id,
      },
    });
  });

  return params;
};

export default (
  plugin: { value?: PluginObject },
  props: IObjectEditProps,
  emits: IObjectEditEmits
) => {
  const state = ref(State.查看);
  /**创建图元，前端传递数据的方式 */
  const createGraphicMetas = (params: CreateGraphicMetas[]) => {
    plugin.value && plugin.value.createGraphicMetas(params);
  };
  let graphicMeta: GraphicMeta|undefined;
  let graphic: ReturnType<GraphicMeta['create'] | GraphicMeta['edit']>|undefined;

  let result: any;
  let allResult: any;
  /**梁山聚义 */
  const doInitOther = async () => {
    if (props.otherObject) {
      let data: CreateGraphicMetas[] | null = null;
      /**逼上梁山 */
      if (isFunction(props.otherObject)) {
        data = await props.otherObject();
      } else if (isArray(props.otherObject)) {
        /**自己上山 */
        data = props.otherObject;
      }
      if (data && data.length > 0) {
        console.log('ddd', data, props);
        if (props.modelValue && props.id) {
          const newData = data.filter((item) => item.geometry.id !== props.id);
          return createGraphicMetas(newData);
        }
        createGraphicMetas(data);
      }
    }
  };
  /**飞向别人的床 */
  const flyToMain = async () => {
    if (!plugin.value) return
    console.log('ffff', props);
    if (props.flyToObject) {
      let data: CreateGraphicMetas[] | null = null;
      /**逼上梁山 */
      if (isFunction(props.flyToObject)) {
        data = await props.flyToObject();
      } else if (isArray(props.flyToObject)) {
        data = props.flyToObject;
      }
      if (data && data.length > 0) {
        await createGraphicMetas(data);

        plugin.value.flyToGraphicMeta(data[0].geometry.id||'', 0.1);
      }
    }
  };
  /**初始化区划图 */
  const initZoningMap = async () => {
    if (!props.topAreaCode) return
    try {
      const res = await getZoningPlan(props.topAreaCode);
      const boundarys: CreateGraphicMetas[] = res.data.map((item) => ({
        geometry: {
          id: item.areaCode,
          type: 'Feature',
          properties: {
            color: '#528FEC80',
            entityOptions: '{"clampToGround":true,"showInterval":[0,1000000]}',
          },
          geometry: item.boundary,
        },
      }));
      //await createGraphicMetas(boundarys.slice(0,1));
      await createGraphicMetas(boundarys);
      if (Object.keys(props.modelValue).length === 0 && !props.flyToObject && boundarys[0]) {
        console.log('飞跃', boundarys[0].geometry);
        plugin.value!.flyToGraphicMeta(boundarys[0].geometry.id||"", 0.1);
      }
    } catch (error) {
      console.error(error);
    }
  };
  const doInit = async () => {
    if (!plugin.value) return;
    try {
      state.value = State.查看;
      result = cloneDeep(
        props.modelValue && isObject(props.modelValue) && Object.keys(props.modelValue).length
          ? props.modelValue
          : undefined
      );
      const params = result
        ? {
            geometry: result,
            properties: cloneDeep(
              props.properties && isObject(props.properties) ? props.properties : {}
            ),
            type: 'Feature',
          }
        : undefined;

      graphicMeta = await plugin.value.editGraphicMeta({
        type: props.type,
        geometry: params,
      });
      if (props.topAreaCode) {
        initZoningMap();
      }
      doInitOther();
      flyToMain();
    } catch (error) {
      console.log(error);
    }
  };

  const doCreate = async () => {
    if (!graphicMeta) return;
    try {
      state.value = !!result ? State.待保存 : State.待创建;
      graphic = graphicMeta[!!result ? 'edit' : 'create']();
      allResult = await graphic.complete;
      result = allResult['geometry'];
      /**直接进入编辑状态 */
      return doCreate();
    } catch (error) {
      console.log(error);
    }
  };
  /**通过geometry获取区划数据 */
  const setAreaBygeometry = async (geo:any) => {
    try {
      const geometryWkt = (window as any).Param3DEngine.CommomUtils.StringifyWKTGeometry(
        geo
      )
      const area = await areaGetByMeta({wktString:geometryWkt})
      if (area.code === 200 && area.data) {
        emits("update:areaCode",area.data.areaCode)
        Reflect.set(allResult,'areaData',area.data)
      }
    } catch (error) {
      console.log(error)
    }
  }

  /**通过坐标计算多边形面积 */
  const calcPolygonArea = (ps:any[]) => {
    try {
      const Cartesian3s = ps.map(item => (window as any).Cesium.Cartesian3.fromDegrees(...item))
      const res = (window as any).Param3DEngine.calcPolygonArea(Cartesian3s) as number
      const area = res?parseFloat(res.toFixed(2)):0
      emits('update:polyonArea',area)
      Reflect.set(allResult,'polyonArea',area)
    } catch (error) {
      console.log(error)
    }
  }

  const doSave = async () => {
    emits('update:modelValue', result);
    emits('update:properties', allResult ? allResult['properties'] : props.properties);
    if (props.needAreaCode) {
      await setAreaBygeometry(result)
    }
    if (props.needPolyonArea && props.type === PlotTypeEnum.POLYGON){
      calcPolygonArea(result.coordinates[0])
    }
    emits('getAllData', allResult);
    props.saveData && props.saveData(allResult);
    doCancel();
  };

  const doReset = () => {
    graphic && graphic.cancle();
    if (!!result && graphicMeta) {
      graphicMeta.clear();
    }
    graphic = undefined;
    result = undefined;
    allResult = undefined;
    doCreate();
  };

  const doRemove = () => {
    graphic && graphic.cancle();
    if (!!result && graphicMeta) {
      graphicMeta.clear();
    }
    graphicMeta && graphicMeta.destroy();
    graphicMeta = undefined;
    graphic = undefined;
    result = undefined;
    allResult = undefined;
  };

  const doCancel = () => {
    doRemove();
    emits('cancel');
  };

  return {
    state,
    doCreate,
    doInit,
    doReset,
    doRemove,
    doSave,
    doCancel,
  };
};
